package com.invengo.library_rfid.analyze.utils.uhf.formatHelp;

import java.util.Arrays;

public class CBookEpcCodeEx extends CEpcCodeEx {
    // 条码号
    public long m_lID = 0;
    // 保留字段
    public long m_lRemain = 0;
    // 保留字段
    public long m_lRemain2 = 0;
    // 图书条码号的长度  version2
    public long m_lIDLength = 0;
    // 条码号 version2
    public String m_szID = "";

    public boolean bFormatResult;


    // 构造函数
    public CBookEpcCodeEx() {
        super();
        m_contentIndex = new CContentIndex();
    }

    // 构造函数
    // <param name="byData">数据</param>
    public CBookEpcCodeEx(byte[] byData) throws Exception {
        super(byData);
        m_contentIndex = new CContentIndex();
        if (byData.length < 12) {
            throw new Exception("CBookEpcCodeEx的EPC数据小于12，无法解析!");
        }
        byte datamodel = byData[0];
//        if ((datamodel& 0xFF) != 194) {
        if (datamodel != 0xC2) {
            CBitClassFromLow tmpBitClass = new CBitClassFromLow(byData);
            String epc = tmpBitClass.toString();
            if ((epc.substring(0, 4).equals("0101") && epc.substring(20, 4).toUpperCase().equals("AB66"))
                    || (epc.substring(0, 4).equals("0202") && epc.substring(20, 4).toUpperCase().equals("AB66"))) {
                bFormatResult = FormatVersion12(byData);
            } else if (epc.substring(0, 15).equals("001002002000055")) {
                bFormatResult = FormatVersion11(byData);
            } else if (epc.startsWith("33")) {
                bFormatResult = FormatVersion28560(byData);
            } else {
                int start_version = 8;
                long encodetype = 0;
                switch ((int) tmpBitClass.getValue(start_version, 6) + 1) {
                    case 1:// 版本1
                    case 2:// 对版本号码为2的，也进行解析
                    case 5:// 对版本号码为5的，也进行解析
                    case 4:// 版本4
                        encodetype = tmpBitClass.getValue(start_version + 6, 2);
                        if (encodetype == 0) {
                            bFormatResult = FormatVersion1011(byData);
                        } else if (encodetype == 1) {
                            bFormatResult = FormatVersion1012(byData);
                        } else {
                            bFormatResult = FormatVersion1010(byData);
                        }
                        break;
                    case 3:// 阿法迪
                        encodetype = tmpBitClass.getValue(start_version + 6, 2);
                        if (encodetype == 0) {
                            bFormatResult = FormatVersion1011(byData);
                        } else if (encodetype == 1) {
                            bFormatResult = FormatVersion1012(byData);
                        } else {
                            bFormatResult = FormatVersion1010(byData);
                        }
                        break;
                    case 45:
                    case 49:
                        bFormatResult = FormatVersion1011(byData);
                        break;
                    default:
                        break;
                }
            }
        }
//        if (datamodel == 0xC2 || bFormatResult == false) {
        if ((datamodel& 0xFF) == 194 || bFormatResult == false) {
            CBitClass tmpBitClass = new CBitClass(byData);
            switch ((int) tmpBitClass.GetValue(90, 4)) {
                case 0:// 版本号异常
                    if (byData.length >= 30) {
                        bFormatResult = FormatVersion2(byData);
                    } else {
                        bFormatResult = FormatVersion1(byData);
                    }
                    break;
                case 1:
                    if (byData.length >= 30) {
                        bFormatResult = FormatVersion2(byData);// 版本号异常
                    } else {
                        bFormatResult = FormatVersion1(byData);
                    }
                    break;
                case 2:
                    bFormatResult = FormatVersion2(byData);
                    break;
                case 3:
                    bFormatResult = FormatVersion3(byData);
                    break;
                case 4:
                    bFormatResult = FormatVersion4(byData);
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public boolean FormatVersion1011(byte[] byData) {
        m_contentIndex = new CContentIndex();
        try {
            CBitClassFromLow bitClass = new CBitClassFromLow(byData);
            m_lStatus = 1; //直接标识为可流通
            m_lTagType = 0;
            m_lBussinessID = 0x00;
            m_nEPCLength = 12;

            //EPC前2个bits位
            m_lLocation = bitClass.getValue(0, 5);      //分拣位，0~4，共5bits   91~95
            m_lSortPort = m_lLocation;
            m_lRemain = bitClass.getValue(5, 2);        //保留，5~6，共2bits    89~90
            //m_lEAS = bitClass.getValue(7, 1);           //安全位，7，共1bits
            m_lEAS = 1 - bitClass.getValue(7, 1);           //安全位，7，共1bits                标签中防盗时存为0，不防盗存为1
            long tmp2 = bitClass.getValue(8, 6) + 1;       //版本号//压缩码与版本号位置互换
            long encodetype = bitClass.getValue(14, 2) + 1;  //压缩码
            m_lVersion = Long.parseLong('1' + String.format("%02d", tmp2) + encodetype); //形成版本号字段
            long tmpIndex1 = bitClass.getValue(16, 8); //content index
            long tmpIndex2 = bitClass.getValue(24, 8); //content index
            m_contentIndex.SetContentIndex(String.format("%08d", Long.parseLong(Long.toBinaryString(tmpIndex1)))
                    + String.format("%08d", Long.parseLong(Long.toBinaryString(tmpIndex2))));
            byte[] byBarCode = new byte[8];
            for (int i = 0; i < 8; i++) {
                byBarCode[i] = byData[i + 4];
            }
            dm_barcode_fromlow barcodeSjtu = new dm_barcode_fromlow();
            m_szID = barcodeSjtu.Decode_sjtu_96(byBarCode);
            m_lIDLength = m_szID.length();
            return true;
        } catch (Exception e) {
            throw new RuntimeException("解析图书标签版本(数据模型_压缩模式00)出错：" + e.getMessage() + " " + e.getStackTrace());
        }
    }

    // 返回EPC数据的Bit数组
    // <param name="byResult">Bit数组</param>
    // <returns>返回数组长度</returns>
    @Override
    public int GetBytes(byte[] byResult) throws Exception {
        if (Long.toString(m_lVersion).length() < 4) {
            CBitClass tmpClass = null;
            switch ((int) m_lVersion) {
                case 1:
                    tmpClass = new CBitClass();
                    AddBitsVersion1(tmpClass);
                    break;
                case 2:
                    tmpClass = new CBitClass(m_nEPCLength);
                    AddBitsVersion2(tmpClass);
                    break;
                case 3:
                    tmpClass = new CBitClass(m_nEPCLength);
                    AddBitsVersion3(tmpClass);
                    break;
                case 4:
                    tmpClass = new CBitClass(m_nEPCLength);
                    AddBitsVersion4(tmpClass);
                    break;
                case 11:
                    tmpClass = new CBitClass(m_nEPCLength);
                    AddBitsVersion11(tmpClass);
                    break;
                case 12:
                    tmpClass = new CBitClass(m_nEPCLength);
                    AddBitsVersion12(tmpClass);
                    break;
                default:
                    throw new Exception("标签版本号有误：" + Long.toString(m_lVersion));
            }
            if (tmpClass == null) {
                return -1;
            } else {
                return tmpClass.GetBytes(byResult);
            }
        } else if (m_lVersion == 28560) {
            CBitClass tmpClass = new CBitClass(m_nEPCLength);
            AddBitsVersion28560(tmpClass);
            return tmpClass.GetBytes(byResult);
        } else {
            CBitClassFromLow tmpClass = null;
            int tmpVersion = Integer.parseInt(Long.toString(m_lVersion).substring(1, 2));
            int encodetype = 0;
            switch (tmpVersion) {
                case 1:
                case 2:// 对版本号码为2的，也进行解析
                case 5:// 对版本号码为5的，也进行解析
                case 4:
                    encodetype = Integer.parseInt(Long.toString(m_lVersion).substring(3, 1));
                    if (encodetype == 1) {
                        m_nEPCLength = 12;
                        tmpClass = new CBitClassFromLow(m_nEPCLength);
                        AddBitsVersion1011(tmpClass);
                    } else if (encodetype == 2) {
                        m_nEPCLength = 16;
                        tmpClass = new CBitClassFromLow(m_nEPCLength);
                        AddBitsVersion1012(tmpClass);
                    } else {
                        m_nEPCLength = 18;
                        tmpClass = new CBitClassFromLow(m_nEPCLength);
                        AddBitsVersion1010(tmpClass);
                    }
                    break;
                case 3:
                    encodetype = Integer.parseInt(Long.toString(m_lVersion).substring(3, 1));
                    if (encodetype == 1) {
                        m_nEPCLength = 12;
                        tmpClass = new CBitClassFromLow(m_nEPCLength);
                        AddBitsVersion1011(tmpClass);
                    } else if (encodetype == 2) {
                        m_nEPCLength = 16;
                        tmpClass = new CBitClassFromLow(m_nEPCLength);
                        AddBitsVersion1012(tmpClass);
                    } else {
                        m_nEPCLength = 18;
                        tmpClass = new CBitClassFromLow(m_nEPCLength);
                        AddBitsVersion1010(tmpClass);
                    }
                    break;
                default:
                    throw new Exception("标签版本号(带数据模型)有误：" + Long.toString(m_lVersion));
            }
            if (tmpClass == null) {
                return -1;
            } else {
                return tmpClass.getBytes(byResult);
            }
        }
    }

    // 构建EPC数据（标签版本1）
    // <param name="bitClass"></param>
    @Override
    public void AddBitsVersion1(CBitClass bitClass) {
        bitClass.AddBits(m_lBussinessID, 8);
        bitClass.AddBits(m_lLibCode, 16);
        bitClass.AddBits(m_lLocation, 8);
        bitClass.AddBits(m_lTagType, 2);
        bitClass.AddBits(m_lStatus, 1);
        bitClass.AddBits(m_lID, 45);
        bitClass.AddBits(m_lSortPort, 5);// yxwu 2014.10.13
        bitClass.AddBits(m_lRemain, 5);
        bitClass.AddBits(m_lVersion, 4);
        bitClass.AddBits(m_lEAS, 2);
    }

    // 格式化数据（标签版本1）
    // <param name="byData">数据</param>
    // <returns>成功返回true，否则返回false</returns>
    @Override
    public boolean FormatVersion1(byte[] byData) throws Exception {
        try {
            if (byData.length < 12) {
                throw new Exception("图书标签Version1.0标签数据长度小于12!");
            }
            CBitClass bitClass = new CBitClass(byData);
            m_lBussinessID = bitClass.GetValue(0, 8);
            m_lLibCode = bitClass.GetValue(8, 16);
            m_lLocation = bitClass.GetValue(24, 8);
            m_lTagType = bitClass.GetValue(32, 2);
            m_lStatus = bitClass.GetValue(34, 1);
            m_lID = bitClass.GetValue(35, 45);
            m_lSortPort = bitClass.GetValue(80, 5);// yxwu 2014.10.13
            m_lRemain = bitClass.GetValue(85, 5);
            m_lVersion = bitClass.GetValue(90, 4);
            m_lEAS = bitClass.GetValue(94, 2);
            m_nEPCLength = 12;
            m_szID = Long.toString(m_lID);
            if (m_lLibCode==9947&&m_lVersion==1&&m_szID.startsWith("1")&&m_szID.length()==8){
                m_szID = m_szID .substring(1,m_szID.length());
            }
            if (m_lLibCode==9777&&m_lVersion==1&&m_szID.startsWith("1")&&m_szID.length()==9){
                m_szID = m_szID .substring(1,m_szID.length());
            }
            return true;
        } catch (Exception e) {
            throw new Exception("解析图书标签版本1出错：" + e.getMessage() + " " + Arrays.toString(e.getStackTrace()));
        }
    }

    // 名称：构建EPC数据（标签版本2）
    // 作者：吴永祥
    // 日期：2011年3月8日
    // <param name="bitClass"></param>
    @Override
    public void AddBitsVersion2(CBitClass bitClass) throws Exception {
        try {
            bitClass.AddBits(m_lBussinessID, 8);
            bitClass.AddBits(m_lLibCode, 16);
            bitClass.AddBits(m_lLocation, 8);
            bitClass.AddBits(m_lTagType, 2);
            bitClass.AddBits(m_lStatus, 1);
            bitClass.AddBits(m_lID, 40);
            bitClass.AddBits(m_lRemain, 5);
            bitClass.AddBits(m_lSortPort, 5);
            bitClass.AddBits(m_lRemain2, 5);
            bitClass.AddBits(m_lVersion, 4);
            bitClass.AddBits(m_lEAS, 2);
            m_lIDLength = m_szID.length();
            bitClass.AddBits(m_lIDLength, 8);
            bitClass.AddBits(m_szID);
        } catch (Exception ex) {
            throw new Exception("组成标签数据流失败：" + ex.getMessage() + " " + Arrays.toString(ex.getStackTrace()));
        }
    }

    // 名称：构建EPC数据（标签版本3）
    // 作者：吴永祥
    // 日期：2011年3月8日
    @Override
    public void AddBitsVersion3(CBitClass bitClass) throws Exception {
        try {
            bitClass.AddBits(m_lBussinessID, 8);
            bitClass.AddBits(m_lLibCode, 16);
            bitClass.AddBits(m_lLocation, 8);
            bitClass.AddBits(m_lTagType, 2);
            bitClass.AddBits(m_lStatus, 1);
            bitClass.AddBits(m_lID, 40);
            bitClass.AddBits(m_lRemain, 5);
            bitClass.AddBits(m_lSortPort, 5);
            bitClass.AddBits(m_lRemain2, 5);
            bitClass.AddBits(m_lVersion, 4);
            bitClass.AddBits(m_lEAS, 2);
            m_lIDLength = m_szID.length();
            if (m_extend_archive_info != null) {
                byte[] byData = m_extend_archive_info.getByte();
                if (byData != null) {
                    bitClass.AddBytes(byData);
                }
            }
        } catch (Exception ex) {
            throw new Exception("组成标签数据流失败：" + ex.getMessage() + " " + Arrays.toString(ex.getStackTrace()));
        }
    }

    // 名称：格式化数据（标签版本2）
    // 作者：吴永祥
    // 日期：2011年3月8日
    // <param name="byData">数据</param>
    // <returns>成功返回true，否则返回false</returns>
    @Override
    public boolean FormatVersion2(byte[] byData) throws Exception {
        try {
            CBitClass bitClass = new CBitClass(byData);
            m_lBussinessID = bitClass.GetValue(0, 8);
            m_lLibCode = bitClass.GetValue(8, 16);
            m_lLocation = bitClass.GetValue(24, 8);
            m_lTagType = bitClass.GetValue(32, 2);
            m_lStatus = bitClass.GetValue(34, 1);
            m_lID = bitClass.GetValue(35, 40);
            m_lRemain = bitClass.GetValue(75, 5);
            m_lSortPort = bitClass.GetValue(80, 5);
            m_lRemain2 = bitClass.GetValue(85, 5);
            m_lVersion = bitClass.GetValue(90, 4);
            m_lEAS = bitClass.GetValue(94, 2);
            if (m_lTagType != 0)// 非图书标签
            {
                return false;
            }
            m_lIDLength = bitClass.GetValue(96, 8);
            String tmpID = "";
            for (int i = 0; i < m_lIDLength; i++) {
                tmpID = tmpID + (char) byData[i + 13];
            }
            m_szID = tmpID;
            m_nEPCLength = 30;
            return true;
        } catch (Exception e) {
            throw new Exception("解析图书标签版本2出错：" + e.getMessage() + " " + Arrays.toString(e.getStackTrace()));
        }
    }
}


